import { getTransformCoordinate } from "../common.js";

// 遮罩层，拖拽图形的操作均在这里进行
export default class Layer {
  constructor() {
    this.loadText = true; // 是否允许在此层级上加载文字（某些图案在旋转状态下无法计算文字的位置）
  }

  // 每次点击的时候都创建一个新的画布，并将选中的图案在新的画布中修改（不改变旧的画布）
  // 在操作完成后再将新画布上的图案数据加载到原有画布上并销毁新画布
  createLayer() {
    let listenerDom;

    if (this.canvasInfoMap.size > 30) {
      // 启用蒙板优化
      this.ctxCopy = document.createElement("canvas"); // 创建的新画布元素
      this.ctxCopy.id = "boardCopy";

      this.ctxCopy.width = this.canvas.width;
      this.ctxCopy.height = this.canvas.height;

      // 获取画布父级的定位方式，根据定位方式来计算蒙版的偏移量，以此来将蒙版和原画布对其
      let parentPositionType = document.defaultView.getComputedStyle(
        this.canvas.parentElement,
        null
      ).position;

      let dom = document.defaultView.getComputedStyle(this.canvas, null);
      let domScaleX = 1;
      let domScaleY = 1;

      this.ctxCopy.style.position = "absolute";
      this.ctxCopy.style.transform = dom.transform;
      this.ctxCopy.style.width = this.canvas.offsetWidth + "px";
      this.ctxCopy.style.height = this.canvas.offsetHeight + "px";

      // 计算缩放比例
      if (dom.transform.indexOf("matrix") !== -1) {
        let scaleValue = dom.transform.split("(")[1].split(")")[0].split(",");
        if (scaleValue.length === 6) {
          domScaleX = scaleValue[0];
          domScaleY = scaleValue[3];
        }
      }

      // console.log(dom.transform.indexOf("matrix"));

      const parentOffset = this.canvas.parentElement.getBoundingClientRect();
      const subOffset = this.canvas.getBoundingClientRect();

      // 计算画布到父级元素的距离
      let subTop = subOffset.top - parentOffset.top;
      let subLeft = subOffset.left - parentOffset.left;

      if (parentPositionType === "relative") {
        // 动态计算位置
        this.ctxCopy.style.top =
          subTop - (this.canvas.offsetHeight * (1 - domScaleY)) / 2 + "px";
        this.ctxCopy.style.left =
          subLeft - (this.canvas.offsetWidth * (1 - domScaleX)) / 2 + "px";
        this.canvas.parentElement.appendChild(this.ctxCopy);
      } else {
        /*
          如果没有设置父级元素 position: relative ，则直接将蒙版插入到 body 中
          插入时，除了插入蒙版外，还需要插入视口，用于限制蒙版的最大宽高
          * 优点：不受到父级节点样式影响（尤其是对于上级节点来说，无法去判断在 dom 结构中，哪一层节点设置了重新定位）
        */
        this.viewport = document.createElement("div");

        if (this.canvas.parentElement.offsetWidth > this.canvas.offsetWidth) {
          this.viewport.style.width = this.canvas.offsetWidth + "px";
        } else {
          this.viewport.style.width =
            this.canvas.parentElement.offsetWidth + "px";
        }
        if (this.canvas.parentElement.offsetHeight > this.canvas.offsetHeight) {
          this.viewport.style.height = this.canvas.offsetHeight + "px";
        } else {
          this.viewport.style.height =
            this.canvas.parentElement.offsetHeight + "px";
        }

        this.viewport.style.position = "absolute";
        this.viewport.style.transform = dom.transform;
        this.viewport.style.overflow = "hidden";
        this.viewport.style.top =
          subOffset.top -
          (this.canvas.offsetHeight * (1 - domScaleY)) / 2 +
          document.documentElement.scrollTop +
          "px";
        this.viewport.style.left =
          subOffset.left -
          (this.canvas.offsetWidth * (1 - domScaleX)) / 2 +
          document.documentElement.scrollLeft +
          "px";
        document.body.appendChild(this.viewport);

        this.ctxCopy.style.top = 0 + "px";
        this.ctxCopy.style.left = 0 + "px";
        this.viewport.appendChild(this.ctxCopy);

        // this.viewport.style.background = 'rgba(0, 250, 0, 0.1)'
      }

      // this.ctxCopy.style.background = "rgba(0, 0, 250, 0.1)";
      // this.ctxCopy.style.marginTop = '50px'
      // this.ctxCopy.style.marginLeft = '-50px'

      if (!this.shadeLayer) this.shadeLayer = this.ctxCopy.getContext("2d");

      this.ctx = this.shadeLayer;
      listenerDom = this.viewport ? this.viewport : this.ctxCopy;
    } else {
      listenerDom = this.canvas;
    }

    // 鼠标 移动/抬起 操作
    let isDrag =
      this.ele && (!(typeof this.ele.drag === "boolean") || this.ele.drag);

    const moveFnc = (val) => {
      let eventProps = getTransformCoordinate(this.canvas, {
        offsetX: val.offsetX,
        offsetY: val.offsetY,
      });

      this.shadeMove(eventProps, isDrag);
    };
    listenerDom.addEventListener("mousemove", moveFnc);

    const upFnc = (val) => {
      let eventProps = getTransformCoordinate(this.canvas, {
        offsetX: val.offsetX,
        offsetY: val.offsetY,
      });
      this.shadeUp(eventProps);
      listenerDom.removeEventListener("mouseup", upFnc);
      listenerDom.removeEventListener("mousemove", moveFnc);
    };
    listenerDom.addEventListener("mouseup", upFnc);
  }

  // 删除当前层
  removeLayer() {
    if (this.viewport) this.viewport.remove();
    if (this.ctxCopy) this.ctxCopy.remove();
  }

  // 鼠标点击事件（通过 this.layer 触发）
  shadeDown() {
    this.createLayer();
  }

  // 鼠标移动时要做的事情
  shadeMove(val, isDrag) {
    queueMicrotask(() => {
      if (this.isDragElement) {
        let obj = JSON.parse(JSON.stringify(this.ele));
        if (!obj.unLight) obj.fillColor = this.highlightColor;
        if (this.signElement) {
          let subX = val.offsetX - this.mouseX;
          let subY = val.offsetY - this.mouseY;
          if (this.signElement.signType === "connect") {
            this.drawLine(
              {
                offsetX: val.offsetX,
                offsetY: val.offsetY,
                startX: this.signElement.signCenterX,
                startY: this.signElement.signCenterY,
              },
              null
            );
            this.drawGetAllLinks();
          } else {
            // 如果选中了标记点，则会改变标记点当前所属于图案的形状，并重新生成标记点
            if (this.ele.type === "line") {
              if (this.reverse) {
                obj.x += subX;
                obj.y += subY;
              } else {
                obj.endX += subX;
                obj.endY += subY;
              }
            } else {
              // 如果是图形，要判断点击的点是缩放还是改变大小
              this.changeShape({ val, obj, subX, subY });
            }
            this.loadText = false;
            this.dragElement(obj);
          }
        } else {
          if (isDrag) {
            // 移动图案
            this.PropAboutX.forEach((i) => {
              obj[i] += val.offsetX - this.mouseX;
            });
            this.PropAboutY.forEach((i) => {
              obj[i] += val.offsetY - this.mouseY;
            });
            this.fixedCenterPoint(obj);
            this.loadText = true;
            this.dragElement(obj);
            this.repaintConnect(); // 重新绘制连线  * 注：最好只在移动图案的时候重新绘制，不然在矩形缩放时会因为计算问题导致连接线坐标计算错误
          }
        }
      }
      // else if (this.isDragCanvas) {
      //   // 移动画布
      //   this.dragCanvas({
      //     x: val.pageX - this.mouseX + this.subX,
      //     y: val.pageY - this.mouseY + this.subY,
      //   });
      // }
      else if (this.drawCanvas) {
        // 创建图案
        if (this.type === "line") {
          this.drawLine(val, null);
        } else if (this.type === "rect") {
          this.drawRect(val, null, true);
        } else if (this.type === "circular") {
          this.drawCircular(val, null, true);
        }
      }
    });
  }

  // 鼠标抬起
  shadeUp(val) {
    this.ctx = this.layer;
    this.abc = val.offsetX; // 此行只是为了调用一下val里面的属性，由于接下来的过程将蒙版移除了，如果不提前调用val内部的属性，会导里面的一些参数发生变化
    this.removeLayer();
    this.shadeLayer = null;
    this.ctxCopy = null;
    this.viewport = null;
    this.loadText = true;
    this.mouseup(val);
  }
}
